package com.uinnova.product.eam.service.impl;

import com.binary.core.exception.BinaryException;
import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.google.common.collect.Lists;
import com.uinnova.product.eam.base.cj.BaseEntity;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.comm.model.es.EamCategory;
import com.uinnova.product.eam.model.EamCategoryCdt;
import com.uinnova.product.eam.model.cj.domain.PlanDesignInstance;
import com.uinnova.product.eam.model.cj.enums.PlanShareEnum;
import com.uinnova.product.eam.model.cj.vo.DiagramPlanVO;
import com.uinnova.product.eam.model.cj.vo.PlanDesignInstanceVO;
import com.uinnova.product.eam.model.cj.vo.PlanDesignResponseVO;
import com.uinnova.product.eam.model.diagram.SpaceResourceResultInfo;
import com.uinnova.product.eam.model.dto.EamCategoryDTO;
import com.uinnova.product.eam.model.enums.AssetType;
import com.uinnova.product.eam.service.EamCategorySvc;
import com.uinnova.product.eam.service.EamRecycleSvc;
import com.uinnova.product.eam.service.cj.service.PlanArtifactService;
import com.uinnova.product.eam.service.cj.service.PlanDesignInstanceService;
import com.uinnova.product.eam.service.cj.service.ShareService;
import com.uinnova.product.eam.service.exception.BusinessException;
import com.uinnova.project.api.diagram.v2.client.ESDiagramApiClient;
import com.uinnova.project.base.diagram.comm.model.ESDiagram;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.permission.base.SysUser;
import com.uino.util.sys.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 回收站相关接口实现
 * @author ch
 */
@Service
@Slf4j
public class EamRecycleSvcImpl implements EamRecycleSvc {

    @Resource
    private EamCategorySvc categorySvc;
    @Resource
    private ESDiagramApiClient diagramApiClient;
    @Resource
    private PlanDesignInstanceService planInstanceService;
    @Resource
    private PlanArtifactService planArtifactService;
    @Resource
    private ShareService shareService;

    public SpaceResourceResultInfo queryResource(Long id, String like) {
        SysUser userInfo = SysUtil.getCurrentUserInfo();
        SpaceResourceResultInfo result = new SpaceResourceResultInfo();
        //查询文件夹
        List<EamCategoryDTO> categoryList = categorySvc.queryRecycleByParentId(id, like, LibType.PRIVATE);
        if(CollectionUtils.isNotEmpty(categoryList)){
            result.setChildrenDirs(categoryList);
        }
        //查询视图
        BoolQueryBuilder diagramQuery = QueryBuilders.boolQuery();
        diagramQuery.must(QueryBuilders.termQuery("isOpen", 0));
        diagramQuery.must(QueryBuilders.termQuery("historyVersionFlag", 1));
        diagramQuery.must(QueryBuilders.termQuery("status", 0));
        diagramQuery.must(QueryBuilders.termQuery("dataStatus", 1));
        diagramQuery.must(QueryBuilders.termQuery("ownerCode.keyword", userInfo.getLoginCode()));
        if(!BinaryUtils.isEmpty(like)){
            diagramQuery.must(QueryBuilders.wildcardQuery("name.keyword", "*" + like + "*"));
            Set<Long> dirIds = categoryList.stream().map(EamCategoryDTO::getId).collect(Collectors.toSet());
            dirIds.add(0L);
            diagramQuery.must(QueryBuilders.termsQuery("dirId", dirIds));
        }else{
            diagramQuery.must(QueryBuilders.termQuery("dirId", id));
        }
        Page<ESDiagram> diagramPage = diagramApiClient.selectListByQuery(1, 200, diagramQuery);
        List<DiagramPlanVO> diagramPlanList = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(diagramPage.getData())){
            for (ESDiagram each : diagramPage.getData()) {
                DiagramPlanVO diagram = new DiagramPlanVO();
                diagram.setAssetType(AssetType.DIAGRAM);
                diagram.setDiagram(each);
                diagramPlanList.add(diagram);
            }
        }
        Page<PlanDesignInstanceVO> planList = planInstanceService.queryRecycleBin(1, 200, id, like);
        if(CollectionUtils.isNotEmpty(planList.getData())){
            for (PlanDesignInstanceVO each : planList.getData()) {
                DiagramPlanVO plan = new DiagramPlanVO();
                plan.setAssetType(AssetType.SCHEME);
                plan.setPlanDesignInstance(EamUtil.copy(each, PlanDesignResponseVO.class));
                diagramPlanList.add(plan);
            }
        }
        result.setDiagramPlanList(diagramPlanList);
        return result;
    }

    /**
     * 目前支持单个（文件夹，视图，方案）的恢复操作
     */
    @Override
    public Integer restoreBatch(EamCategoryCdt cdt) {
        SysUser user = SysUtil.getCurrentUserInfo();
        String loginCode = user.getLoginCode();
        LibType libType = cdt.getLibType();
        List<String> diagramIds = cdt.getDiagramIds();
        List<Long> planIds = cdt.getPlanIds();
        if (BinaryUtils.isEmpty(diagramIds) && BinaryUtils.isEmpty(cdt.getDirIds()) && BinaryUtils.isEmpty(planIds)) {
            throw new BusinessException("请指定还原的视图,方案或文件夹");
        }
        //恢复文件夹；
        if(!BinaryUtils.isEmpty(cdt.getDirIds())){
            //获取当前文件夹及所有子文件夹
            List<EamCategory> categoryList = categorySvc.queryByBatchId(cdt.getDirIds(), 0, loginCode, libType);
            List<Long> oldParentIds = categoryList.stream().filter(each->cdt.getDirIds().contains(each.getId())).map(EamCategory::getOldParentId).collect(Collectors.toList());
            List<EamCategory> parentCategory = categorySvc.getByIds(oldParentIds, libType);
            Map<Long, EamCategory> parentCategoryMap = new HashMap<>();
            if(!BinaryUtils.isEmpty(parentCategory)){
                parentCategoryMap = parentCategory.stream().collect(Collectors.toMap(EamCategory::getId, each -> each, (k1, k2) -> k1));
            }
            categoryList.sort(Comparator.comparing(EamCategory::getDirLvl));
            for (EamCategory category : categoryList) {
                category.setDataStatus(1);
                EamCategory parent = parentCategoryMap.get(category.getOldParentId());
                if(!BinaryUtils.isEmpty(parent) && parent.getDataStatus()!=0){
                    category.setParentId(category.getOldParentId());
                    category.setDirPath(parent.getDirPath()+category.getId()+"#");
                    category.setDirLvl(parent.getDirLvl()+1);
                }else{
                    category.setParentId(0L);
                    category.setDirPath("#"+category.getId()+"#");
                    category.setDirLvl(1);
                }
                parentCategoryMap.put(category.getId(), category);
            }
            categorySvc.saveOrUpdateList(categoryList,libType);
            //恢复文件夹下的视图
            List<Long> dirIds = categoryList.stream().map(EamCategory::getId).distinct().collect(Collectors.toList());
            List<ESDiagram> diagrams = diagramApiClient.selectDiagramsFromRecycle(dirIds, loginCode,new ArrayList<>());
            if(!BinaryUtils.isEmpty(diagrams)){
                //此部分逻辑，视图是根据文件夹下查出来的，故而dirId不用动；
                diagrams.forEach(each -> each.setStatus(1));
                diagramApiClient.saveOrUpdateBatch(diagrams);
            }
            // 恢复文件夹下的方案；
            List<PlanDesignInstance> planList = planInstanceService.getRecyclePlanByDirId(new HashSet<>(dirIds));
            if(CollectionUtils.isNotEmpty(planList)){
                restorePlan(planList.stream().map(BaseEntity::getId).collect(Collectors.toList()));
            }
        }

        //恢复视图
        if(!BinaryUtils.isEmpty(diagramIds)){
            //此部分逻辑，视图是根据文件夹下查出来的。故而dirId不用动；
            List<ESDiagram> esDiagrams = diagramApiClient.selectDiagramsFromRecycle(new ArrayList<>(),loginCode,diagramIds);
            if(BinaryUtils.isEmpty(esDiagrams)){
                return 1;
            }
            List<Long> dirIds = esDiagrams.stream().map(ESDiagram::getOldDirId).filter(e -> !e.equals(0L)).distinct().collect(Collectors.toList());
            Map<Long, EamCategory> restoreMap = new HashMap<>();
            List<EamCategory> restoreCategory = categorySvc.getByIds(dirIds, libType);
            if(CollectionUtils.isNotEmpty(restoreCategory)){
                restoreMap = restoreCategory.stream().collect(Collectors.toMap(EamCategory::getId, e->e, (k1,k2)->k2));
            }
            //待还原视图不为空
            for (ESDiagram each : esDiagrams) {
                EamCategory restore = restoreMap.get(each.getOldDirId());
                long oldDirId = restore==null||restore.getDataStatus()==0 ? 0L : each.getOldDirId();
                each.setDirId(oldDirId);
                each.setStatus(1);
            }
            diagramApiClient.saveOrUpdateBatch(esDiagrams);
        }
        //恢复方案
        if(!BinaryUtils.isEmpty(planIds)){
            restorePlan(planIds);
        }
        return null;
    }

    private void restorePlan(List<Long> planIdList) {
        planInstanceService.recoverBatch(planIdList, null);
        planArtifactService.handlePlanArtifact(planIdList, 1);
        // 恢复分享出去的方案
        shareService.deleteOrRecoverySharePlan(planIdList, PlanShareEnum.SHARING.getStatus());
    }

    @Override
    public Integer deleteBatch(EamCategoryCdt cdt) {

        /**
         * 回收站内存在：普通文件夹，普通视图，方案；
         * 模型文件夹以及模型主视图，在删除时是做的物理删除；
         */
        //文件夹
        List<Long> dirIds = cdt.getDirIds();
        //视图
        List<String> diagramIds = cdt.getDiagramIds();
        //方案
        List<Long> planIds = cdt.getPlanIds();
        if (BinaryUtils.isEmpty(dirIds) && BinaryUtils.isEmpty(diagramIds) && BinaryUtils.isEmpty(planIds)) {
            throw new BinaryException("请选择待删除的内容（文件夹/方案/视图）");
        }
        String loginCode = SysUtil.getCurrentUserInfo().getLoginCode();
        LibType libType = cdt.getLibType();
        //物理删除普通文件夹
        if (!BinaryUtils.isEmpty(dirIds)) {
            //查询所有文件夹
            List<EamCategory> categoryList = categorySvc.getByIds(cdt.getDirIds(), cdt.getLibType());
            List<EamCategory> delList = new ArrayList<>();
            for (EamCategory each : categoryList) {
                List<EamCategory> childList = categorySvc.queryByRootId(each.getId(), 0, each.getOwnerCode(), cdt.getLibType());
                delList.addAll(childList);
            }
            delList.sort(Comparator.comparing(EamCategory::getDirLvl));
            List<Long> ids = delList.stream().map(EamCategory::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            //对文件夹进行物理删除
            categorySvc.delByIds(ids, cdt.getLibType());
            //查询并删除文件夹下的视图
            String ownerCode = LibType.PRIVATE.equals(libType) ? loginCode : null;
            int open = LibType.PRIVATE.equals(libType) ? 0 : 1;
            List<ESDiagram> diagrams = diagramApiClient.selectByDirIds(ids, null, ownerCode, Lists.newArrayList(open));
            if (!BinaryUtils.isEmpty(diagrams)) {
                List<Long> idList = diagrams.stream().map(ESDiagram::getId).collect(Collectors.toList());
                diagramApiClient.deleteDiagramByIds(idList.toArray(new Long[]{}));
            }
            //查询并删除文件夹下的方案
            HashSet<Long> setDirIds = new HashSet<>(dirIds);
            List<PlanDesignInstance> planList = planInstanceService.findPlanListByDirIds(setDirIds);
            if (!BinaryUtils.isEmpty(planList)) {
                List<Long> planIdList = planList.stream().map(PlanDesignInstance::getId).collect(Collectors.toList());
                planInstanceService.removeFromRecycleBinBatch(planIdList,null);
            }
        }
        //删除视图
        if (!BinaryUtils.isEmpty(diagramIds)) {
            Long[] ids = diagramApiClient.queryDBDiagramInfoBydEnergy(diagramIds.toArray(new String[]{}));
            diagramApiClient.deleteDiagramByIds(ids);
        }
        //删除方案
        if (!BinaryUtils.isEmpty(planIds)) {
            planInstanceService.removeFromRecycleBinBatch(planIds,null);
        }
        return null;
    }

    @Override
    public String restoreCheck(EamCategoryCdt cdt) {
        String loginCode = SysUtil.getCurrentUserInfo().getLoginCode();
        Set<Long> restoreDirIds = new HashSet<>();
        if(CollectionUtils.isNotEmpty(cdt.getDirIds())){
            List<EamCategory> categoryList = categorySvc.getByIds(cdt.getDirIds(), LibType.PRIVATE);
            if(CollectionUtils.isNotEmpty(categoryList)){
                restoreDirIds.addAll(categoryList.stream().map(EamCategory::getOldParentId).filter(e->!e.equals(0L)).collect(Collectors.toSet()));
            }
        }
        if(CollectionUtils.isNotEmpty(cdt.getDiagramIds())){
            List<ESDiagram> diagrams = diagramApiClient.selectDiagramsFromRecycle(null, loginCode, cdt.getDiagramIds());
            if(CollectionUtils.isNotEmpty(diagrams)){
                restoreDirIds.addAll(diagrams.stream().map(ESDiagram::getOldDirId).filter(e->!e.equals(0L)).collect(Collectors.toSet()));
            }
        }
        if(CollectionUtils.isNotEmpty(cdt.getPlanIds())){
            List<PlanDesignInstance> planList = planInstanceService.getByIds(cdt.getPlanIds());
            if(CollectionUtils.isNotEmpty(planList)){
                restoreDirIds.addAll(planList.stream().map(e->e.getTemp().getDirId()).filter(e->!e.equals(0L)).collect(Collectors.toSet()));
            }
        }
        if(CollectionUtils.isEmpty(restoreDirIds)){
            return null;
        }
        List<EamCategory> resultList = categorySvc.getByIds(new ArrayList<>(restoreDirIds), LibType.PRIVATE);
        resultList = resultList.stream().filter(e -> e.getDataStatus() == 1).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(resultList) || resultList.size()<restoreDirIds.size()){
            return "您还原的文件的上级目录已被删除，还原后该文件将放置在根目录!";
        }
        return null;
    }

}
